package com.hp.team.bookstore.service.order;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hp.team.bookstore.dbaccess.dao.order.PORequirementsHibernateDAO;
import com.hp.team.bookstore.dbaccess.dao.order.PurchaseOrderHibernateDAO;
import com.hp.team.bookstore.model.ICommonConstants;
import com.hp.team.bookstore.model.order.PORequirement;
import com.hp.team.bookstore.model.order.POStatus;
import com.hp.team.bookstore.model.order.PurchaseOrder;
import com.hp.team.bookstore.service.exception.BadOperationException;
import com.hp.team.bookstore.service.order.common.Status;

@Service
public class PurchaseOrderService extends OrderService {

	@Autowired
	private PurchaseOrderHibernateDAO orderDAO;

	@Autowired
	private PORequirementsHibernateDAO poRequirementsDAO;

	public PurchaseOrderService() {
		setOperationsFile("po_operations.xml");
	}

	private POStatus getStatus(String status) {
		if (status != null & !status.isEmpty()) {
			return POStatus.valueOf(status.toUpperCase().replace(" ", "_"));
		}
		return null;
	}

	protected String getCreatorRoleName() {
		return ICommonConstants.ROLE_PURCHASE_SPECIALIST;
	}

	@Transactional
	public Map<PurchaseOrder, Set<POStatus>> getOrdersMap(String role, String operation) throws BadOperationException {

		initOperation(role, operation);

		Map<PurchaseOrder, Set<POStatus>> ordersMap = new TreeMap<PurchaseOrder, Set<POStatus>>();
		for (String fromStatus : getCurrentStatusPaths().keySet()) {
			Set<PurchaseOrder> orders = getOrdersList(getStatus(fromStatus));
			ordersMap.putAll(constructOrdersMap(orders));
		}

		return ordersMap;
	}

	@Transactional
	public Map<PurchaseOrder, Set<POStatus>> getOrdersMap(String status, long creatorId) {
		Set<PurchaseOrder> orders = getOrdersList(getStatus(status), creatorId);
		return constructOrdersMap(orders);
	}

	private Map<PurchaseOrder, Set<POStatus>> constructOrdersMap(Set<PurchaseOrder> orders) {
		Map<PurchaseOrder, Set<POStatus>> foundOrders = new TreeMap<PurchaseOrder, Set<POStatus>>();

		for (String fromStatus : getCurrentStatusPaths().keySet()) {

			for (PurchaseOrder order : orders) {

				if (order.getStatus().toString().equalsIgnoreCase(fromStatus)) {
					Set<POStatus> toStatusList = new TreeSet<POStatus>();
					for (String toStatus : getCurrentStatusPaths().get(fromStatus)) {
						toStatusList.add(getStatus(toStatus));
					}
					foundOrders.put(order, toStatusList);
				}
			}
		}

		System.out.println("Found orders: " + foundOrders);
		return foundOrders;
	}

	private Set<PurchaseOrder> getOrdersList(POStatus status) {
		PurchaseOrder exampleOrder = new PurchaseOrder();
		if (status != null) {
			exampleOrder.setStatus(status);
		}
		return new TreeSet<PurchaseOrder>(orderDAO.findByExample(exampleOrder));
	}

	private Set<PurchaseOrder> getOrdersList(POStatus status, long creatorId) {
		PurchaseOrder exampleOrder = new PurchaseOrder();

		if (status != null) {
			exampleOrder.setStatus(status);
		}
		
		List<PurchaseOrder> orders = creatorId != -1 ? orderDAO.findByCreator(exampleOrder, creatorId) : orderDAO.findByExample(exampleOrder);

		return new TreeSet<PurchaseOrder>(orders);
	}

	public Map<PurchaseOrder, Set<POStatus>> removeFromOrdersMap(Map<PurchaseOrder, Set<POStatus>> orders, Long... orderIDs) {
		
		Map<PurchaseOrder, Set<POStatus>> newOrdersMap = new TreeMap<PurchaseOrder, Set<POStatus>>();

		for (Entry<PurchaseOrder, Set<POStatus>> entry : orders.entrySet()) {
			for (long orderId : orderIDs) {
				if (entry.getKey().getId() != orderId) {
					newOrdersMap.put(entry.getKey(), entry.getValue());
				}
			}
		}

		return newOrdersMap;
	}

	public PurchaseOrder getFromOrdersMap(Map<PurchaseOrder, Set<POStatus>> orders, long orderId) {

		for (PurchaseOrder order : orders.keySet()) {
			if (order.getId() == orderId) {
				return order;
			}
		}

		return null;
	}

	public Set<POStatus> getAllAllowedStatuses() {
		Set<POStatus> statuses = new TreeSet<POStatus>();

		for (Status status : getCurrentOperation().getStatuses()) {
			statuses.add(getStatus(status.getFrom()));
		}

		return statuses;
	}

	@Transactional
	public void changeStatus(long orderId, String fromStatus, String toStatus) {
		PurchaseOrder order = orderDAO.findById(orderId, true);

		if (order.getStatus().equals(getStatus(fromStatus))) {
			setStatus(order, getStatus(toStatus));
		}
	}

	private void setStatus(PurchaseOrder order, POStatus status) {
		order.setStatus(status);
		orderDAO.makePersistent(order);

		if (status.equals(POStatus.APPROVED)) {
			// call WS to ship order
		}
	}

	@Transactional
	public Set<PORequirement> getPORequirements() {
		return new TreeSet<PORequirement>(poRequirementsDAO.findAll());
	}

	public Map<PurchaseOrder, Set<POStatus>> checkNewShippedPurchaseOrder(Map<PurchaseOrder, Set<POStatus>> orders) {
		//
		// TestClass testMe = new TestClass();
		// hello = testMe.sayHello("Mina from TestClass");
		// System.out.println(hello);
		//
		// PurchaseOrderHandlerService purchaseOrderHandlerService = new
		// PurchaseOrderHandlerService();
		// PurchaseOrderHandler purchaseOrderHandler =
		// purchaseOrderHandlerService.getPurchaseOrderHandlerPort();
		//
		// Set<Long> orderIDs = new TreeSet<Long>();
		//
		// for (PurchaseOrder order : orders.keySet()) {
		// boolean shipped =
		// purchaseOrderHandler.isShippedPurchaseOrder(order.getId());
		// if (shipped) {
		// changeStatus(order.getId(), POStatus.APPROVED.toString(),
		// POStatus.SHIPPED.toString());
		// orderIDs.add(order.getId());
		// }
		// }
		//
		// return removeFromOrdersMap(orders, orderIDs.toArray(new
		// Long[orderIDs.size()]));
		return null;
	}
}
